home *** CD-ROM | disk | FTP | other *** search
- /*****
- *
- * FileUtil.c
- *
- * This is a support file for "Grant's CGI Framework".
- * Please see the license agreement that accompanies the distribution package
- * for licensing details.
- *
- * Copyright ©1995,1996 by Grant Neufeld
- * grant@acm.com
- * http://arpp.carleton.ca/grant/mac/grantscgi/
- *
- *****/
-
- #include "MyConfiguration.h"
-
- #include <Aliases.h>
- #include <string.h>
-
- #include "compiler_stuff.h"
-
- #include "DebugUtil.h"
- #include "MemoryUtil.h"
-
- #include "FileUtil.h"
-
-
- /*** LOCAL VARIABLES ***/
-
- /*** LOCAL CONSTANTS ***/
-
- /*** LOCAL PROTOTYPES ***/
-
- /*** FUNCTIONS ***/
-
- /* the data returned will not be null terminated */
- OSErr
- FileReadBytes ( short fileRef, long start, long lineLength, char *theLine, long *bytesRead )
- {
- OSErr theErr;
- long lineSize;
-
- my_assert ( fileRef != nil, "\pmyFileReadBytes: fileRef is nil" );
- my_assert ( lineLength != nil, "\pmyFileReadBytes: lineLength is nil" );
- my_assert ( theLine != NULL, "\pmyFileReadBytes: theLine ptr is NULL" );
- my_assert ( bytesRead != NULL, "\pmyFileReadBytes: bytesRead ptr is NULL" );
-
- theErr = SetFPos ( fileRef, fsFromStart, start );
- if ( theErr != noErr )
- {
- goto EXIT_FUNCTION;
- }
-
- lineSize = lineLength - 1;
-
- theErr = FSRead ( fileRef, bytesRead, theLine );
- if ( (theErr != noErr) && (theErr != eofErr) )
- {
- theLine[nil] = nil;
- goto EXIT_FUNCTION;
- }
-
- /* make sure the string is terminated */
- theLine[lineSize] = nil;
-
-
- EXIT_FUNCTION:
-
- return (theErr == eofErr)? noErr : theErr;
- } /* FileReadBytes */
-
-
- /* Finder alias handling */
- #pragma mark -
-
- /* From Apple Developer Support: New Technical Notes;
- "FL 29/30? Resolving Alias File Quietly"
- Set the last Boolean (mountRemoteVols) to true to avoid the resolving of
- aliases that map to unmounted volumes. You definitly want to do that
- because you don't want the user interface for mounting remote volumes
- coming up on servers when there's no one around to deal with that interface. */
- pascal OSErr
- ResolveAliasFileMountOption ( FSSpec *fileFSSpec, Boolean resolveAliasChains,
- Boolean *targetIsFolder, Boolean *wasAliased, Boolean mountRemoteVols )
- {
- /* maximum number of aliases to resolve before giving up */
- #define MAXCHAINS 10
-
- short myResRefNum;
- Handle alisHandle;
- FSSpec initFSSpec;
- Boolean updateFlag;
- Boolean foundFlag;
- Boolean wasAliasedTemp;
- Boolean specChangedFlag;
- short chainCount;
- OSErr retCode;
-
- if ( (fileFSSpec == NULL) || (targetIsFolder == nil) || (wasAliased == nil) )
- {
- return paramErr;
- }
-
- initFSSpec = *fileFSSpec; /* so FSSpec can be restored in case of error */
- chainCount = MAXCHAINS; /* circular alias chain protection */
- myResRefNum = -1; /* resource file not open */
-
- *targetIsFolder = foundFlag = specChangedFlag = false;
-
- /* loop through chain of alias files */
- do
- {
- chainCount--;
-
- /* check if FSSpec is an alias file or a directory.
- note that targetIsFolder => NOT wasAliased */
- retCode = IsAliasFile ( fileFSSpec, wasAliased, targetIsFolder );
- if ( (retCode != noErr) || !(*wasAliased) )
- {
- break;
- }
-
- /* get the resource file reference number */
- myResRefNum = FSpOpenResFile ( fileFSSpec, fsCurPerm );
- retCode = ResError ();
- if ( myResRefNum == -1 )
- {
- break;
- }
-
- /* the first 'alis' resource in the file is the appropriate alias */
- alisHandle = Get1IndResource ( rAliasType, 1 );
- retCode = ResError ();
- if ( alisHandle == nil )
- {
- break;
- }
-
- /* load the resource explicitly in case SetResLoad(FALSE) */
- LoadResource ( alisHandle );
- retCode = ResError ();
- if ( retCode != noErr )
- {
- break;
- }
-
- retCode = FollowFinderAlias ( fileFSSpec, (AliasHandle)alisHandle, mountRemoteVols, fileFSSpec, &updateFlag );
-
- /* FollowFinderAlias returns nsvErr if volume not mounted */
- if ( retCode == noErr )
- {
- if ( updateFlag )
- {
- /* the resource in the alias file needs updating */
- ChangedResource ( alisHandle );
- WriteResource ( alisHandle );
- }
-
- specChangedFlag = true; /* in case of error, restore file spec */
- retCode = IsAliasFile ( fileFSSpec, &wasAliasedTemp, targetIsFolder );
- if ( retCode == noErr )
- {
- /* we're done unless it was an alias file and we're following a chain */
- foundFlag = !(wasAliasedTemp && resolveAliasChains);
- }
- }
-
- CloseResFile( myResRefNum );
- myResRefNum = -1;
- } while ( (retCode == noErr) && (chainCount > nil) && !(foundFlag) );
-
- /* return file not found error for circular alias chains */
- if ( (chainCount == nil) && !(foundFlag) )
- {
- retCode = fnfErr;
- }
-
- /* if error occurred, close resource file and restore the original FSSpec */
- if ( myResRefNum != -1 )
- {
- CloseResFile ( myResRefNum );
- }
-
- if ( (retCode != noErr) && specChangedFlag )
- {
- *fileFSSpec = initFSSpec;
- }
-
- return retCode;
- } /* ResolveAliasFileMountOption */
-
-
- /* sets aliasFileFlag if the FSSpec points to an alias file;
- sets folderFlag if the FSSpec points to a folder */
- pascal OSErr
- IsAliasFile ( const FSSpec *fileFSSpec, Boolean *aliasFileFlag, Boolean *folderFlag )
- {
- CInfoPBRec myCInfoPBRec;
- OSErr retCode;
-
- if ( (fileFSSpec == NULL) || (aliasFileFlag == nil) || (folderFlag == nil) )
- {
- return paramErr;
- }
-
- *aliasFileFlag = *folderFlag = false;
-
- /* get the item's catalog information */
- myCInfoPBRec.hFileInfo.ioCompletion = NULL;
- myCInfoPBRec.hFileInfo.ioNamePtr = (StringPtr)(fileFSSpec->name);
- myCInfoPBRec.hFileInfo.ioVRefNum = fileFSSpec->vRefNum;
- myCInfoPBRec.hFileInfo.ioDirID = fileFSSpec->parID;
- myCInfoPBRec.hFileInfo.ioFVersNum = nil;
- /* MFS compatibility, see TN #204 */
- myCInfoPBRec.hFileInfo.ioFDirIndex = nil;
-
- retCode = PBGetCatInfoSync ( &myCInfoPBRec );
-
- /* set aliasFileFlag if the item is not a directory and the aliasFile bit is set */
- if ( retCode == noErr )
- {
- /* check directory bit */
- if ( (myCInfoPBRec.hFileInfo.ioFlAttrib & ioDirMask) != nil )
- {
- *folderFlag = true;
- }
- /* check isAlias bit */
- else if ( (myCInfoPBRec.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) != nil )
- {
- *aliasFileFlag = true;
- }
- }
-
- return retCode;
- } /* IsAliasFile */
-
-
- /* this is included in the newer header files, so has been removed */
- #if 0
- /* FollowFinderAlias resolves an alias taken from a Finder alias file,
- updating the alias record (but not the alias resource in the file) if necessary.
- Warning: This trap is used internally by Apple Computer, Inc.
- It has not been tested for use by application software.
- While we do not anticipate any problems, it is the responsibility of the developer
- to ensure that it operates appropriately and reliably for their application. */
- pascal OSErr
- FollowFinderAlias ( const FSSpec *fromFile, AliasHandle alias, Boolean logon, FSSpec *target, Boolean *wasChanged )
- = {0x700F, 0xA823}; /* MOVEQ #$0F,D0; _AliasDispatch; */
- #endif /* 0 */
-
-
- /***** EOF *****/
-